﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Linq.Expressions;
using System.Reflection;

namespace IMKSplit
{    

    public partial class IMKSplit : Form
    {        
        public delegate void ThreadSafeResetBindingDelegate(BindingSource source);
        public ThreadSafeResetBindingDelegate bindingDelegate;

        #region // Attributes

        List<FileRow> splitFileList;
        BindingSource splitSource;
        Thread splitThread;

        List<FileRow> joinFileList;
        BindingSource joinSource;
        Thread joinThread;

        int rowIndex = 0;
        #endregion // Attributes

        #region // Constructor
        public IMKSplit()
        {
            InitializeComponent();
            initSplit();
            initJoin();
            bindingDelegate = new ThreadSafeResetBindingDelegate(ThreadSafeResetBinding);
        }
        #endregion // Constructor

        private void initSplit()
        {

            splitFileList = new List<FileRow>();
            splitSource = new BindingSource();
            splitSource.DataSource = splitFileList;
            dataGridViewSplit.AutoGenerateColumns = false;
            dataGridViewSplit.DataSource = splitSource;
        }

        private void initJoin()
        {
            joinFileList = new List<FileRow>();
            joinSource = new BindingSource();
            joinSource.DataSource = joinFileList;
            dataGridViewJoin.AutoGenerateColumns = false;
            dataGridViewJoin.DataSource = joinSource;
        }

        private void IMKSplit_Load(object sender, EventArgs e)
        {
            addColumns(dataGridViewSplit);
            addColumns(dataGridViewJoin);       
        }

        private void addColumns(DataGridView dgv)
        {
            DataGridViewTextBoxColumn filenameColumn = new DataGridViewTextBoxColumn();
            filenameColumn.Name = "Filepath";
            filenameColumn.DataPropertyName = "filepath";
            filenameColumn.ReadOnly = false;

            DataGridViewTextBoxColumn sizeColumn = new DataGridViewTextBoxColumn();
            sizeColumn.Name = "Size (KB)";
            sizeColumn.DataPropertyName = "size";
            sizeColumn.ReadOnly = false;

            DataGridViewTextBoxColumn splitSizeColumn = null;
            if (dgv == dataGridViewSplit)
            {
                splitSizeColumn = new DataGridViewTextBoxColumn();            
                splitSizeColumn.Name = "Split Size(in KB)";
                splitSizeColumn.DataPropertyName = "splitSize";
            }
            DataGridViewTextBoxColumn splitCountColumn = new DataGridViewTextBoxColumn();                                                  
            splitCountColumn.Name = "Split Count";
            splitCountColumn.DataPropertyName = "splitCount";            

            DataGridViewTextBoxColumn progressColumn = new DataGridViewTextBoxColumn();
            progressColumn.Name = "Progress";
            progressColumn.DataPropertyName = "progress";
            progressColumn.ReadOnly = false;

            dgv.Columns.Add(filenameColumn);
            dgv.Columns.Add(sizeColumn);
            if (dgv == dataGridViewSplit)
            {
                dgv.Columns.Add(splitSizeColumn);
            }   
            dgv.Columns.Add(splitCountColumn);                          
            dgv.Columns.Add(progressColumn);
        }

        private void dataGridViewSplit_DragDrop(object sender, DragEventArgs e)
        {            
            
            string[] droppedFilePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
            int defaultSplitCount = 5;

            foreach (string path in droppedFilePaths)
            {
                FileInfo fi = new FileInfo(path);                
                //size ditampilkan dalam KB
                splitFileList.Add(new FileRow { filepath = fi.Name, size = "" + (fi.Length / 1024), splitCount = defaultSplitCount, splitSize = (fi.Length / (defaultSplitCount*1024)), progress = "0%" });                
            }
            splitSource.ResetBindings(false);

            if (dataGridViewSplit.RowCount > 0)
            {
                rowIndex = dataGridViewSplit.SelectedRows[0].Index;
                System.Diagnostics.Debug.WriteLine("row enter: " + dataGridViewSplit.SelectedRows[0].Index);
                textBox1.Text = dataGridViewSplit[2, rowIndex].Value.ToString();
                textBox2.Text = dataGridViewSplit[3, rowIndex].Value.ToString();
            }
            else
            {
                textBox1.Text = "0";
                textBox2.Text = "0";
            }

            label4.Visible = false;
            label4.Enabled = false;
        }

        private void dataGridViewSplit_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        }

        private void dataGridViewSplit_DragLeave(object sender, EventArgs e)
        {
        }

        private void buttonBrowseSplit_Click(object sender, EventArgs e)
        {                        
            #region // kerjaan mp
            string folderPath = "";
            
            FolderBrowserDialog folderBrowseDialog = new FolderBrowserDialog();
            folderBrowseDialog.Description = "Select file to split"; 
            
            if (folderBrowseDialog.ShowDialog() == DialogResult.OK)
            {
                folderPath = folderBrowseDialog.SelectedPath;                             
                this.textBoxFileDestinationSplit.Text = folderPath;
            }
            #endregion // kerjaan mp
        }

        private void dataGridViewJoin_DragDrop(object sender, DragEventArgs e)
        {            
            string[] droppedFilePaths = (string[])e.Data.GetData(DataFormats.FileDrop);            

            foreach (string path in droppedFilePaths)
            {
                FileInfo fi = new FileInfo(path);
                //size ditampilkan dalam KB
                joinFileList.Add(new FileRow { filepath = fi.Name, size = "" + (fi.Length / 1024), progress = "0%", splitCount=10 });
            }
            joinSource.ResetBindings(false);
        }

        private void dataGridViewJoin_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        }

        private void dataGridViewJoin_DragLeave(object sender, EventArgs e)
        {
        }
       
        private void buttonBrowseJoin_Click(object sender, EventArgs e)
        {
            #region // kerjaan mp
            string folderPath = "";

            FolderBrowserDialog folderBrowseDialog = new FolderBrowserDialog();
            folderBrowseDialog.Description = "Select file to split";

            if (folderBrowseDialog.ShowDialog() == DialogResult.OK)
            {
                folderPath = folderBrowseDialog.SelectedPath;                
                this.textBoxFileDestinationJoin.Text = folderPath;
            }
            #endregion // kerjaan mp
        }

        private void split()
        {
            foreach (var splitFile in splitFileList)
            {
                while (splitFile.realProgress<splitFile.splitCount)
                {
                    splitFile.realProgress++;
                    Thread.Sleep(500);
                    splitFile.progress = ((splitFile.realProgress * 100)/splitFile.splitCount) + "% ("+ splitFile.realProgress + " of " + splitFile.splitCount + ")";
                    dataGridViewSplit.Invoke(bindingDelegate, splitSource);                    
                }
            }
            System.Diagnostics.Debug.WriteLine("split selesai");
        }

        private void pictureBoxSplit_Click(object sender, EventArgs e)
        {            
            splitThread = new Thread(new ThreadStart(split));
            splitThread.Start();            

            while (!splitThread.IsAlive) ; // nunggu thread-nya hidup
        }

        private void join()
        {
            foreach (var joinFile in joinFileList)
            {
                while (joinFile.realProgress < joinFile.splitCount)
                {
                    joinFile.realProgress++;
                    Thread.Sleep(500);
                    joinFile.progress = ((joinFile.realProgress * 100) / joinFile.splitCount) + "% (" + joinFile.realProgress + " of " + joinFile.splitCount + ")";
                    dataGridViewJoin.Invoke(bindingDelegate, joinSource);
                }
            }
            System.Diagnostics.Debug.WriteLine("join selesai");
        }

        private void pictureBoxJoin_Click(object sender, EventArgs e)
        {
            joinThread = new Thread(new ThreadStart(join));
            joinThread.Start();

            while (!joinThread.IsAlive) ; // nunggu thread-nya hidup
        }

        public void ThreadSafeResetBinding(BindingSource bindingsource)
        {
            bindingsource.ResetBindings(false);
        }
        private void dataGridViewSplit_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            #region // kerjaan mp
            int columnIndex = dataGridViewSplit.CurrentCell.ColumnIndex;
            int rowIndex = dataGridViewSplit.CurrentCell.RowIndex;
            string currentValue = dataGridViewSplit.CurrentCell.Value.ToString();
            if (columnIndex == 2 || columnIndex == 3)
            {
                if (dataGridViewSplit[1, rowIndex].Value != null)
                // jika filenya ada
                {
                    int value = Int32.Parse(currentValue);
                    int newSplit = Int32.Parse(dataGridViewSplit[1, rowIndex].Value.ToString());
                    newSplit /= value;
                        
                    if (dataGridViewSplit.CurrentCell.ColumnIndex == 2)
                    // jika kolom yang diedit adalah Split Size
                    {
                        dataGridViewSplit[3, rowIndex].Value = newSplit;
                    }
                    else if (dataGridViewSplit.CurrentCell.ColumnIndex == 3)
                    // jika kolom yang diedit adalah Split Count
                    {
                        dataGridViewSplit[2, rowIndex].Value = newSplit;
                    }
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("File kosong.");
                }
            }
            else 
            {
                // niatnya sih mengembalikan value-nya seperti sebelum diedit
                // tapi ternyata tidak bisa (ga tau caranya)
                dataGridViewSplit.CurrentCell.Value = currentValue;                  
            }

            #endregion // kerjaan mp
        }

        private void pictureBoxSplit_MouseDown(object sender, MouseEventArgs e)
        {
            PictureBox pb = sender as PictureBox;
            pb.Size = new Size(50, 50);
            pb.Location = new Point(724, 235);            
        }

        private void pictureBoxSplit_MouseUp(object sender, MouseEventArgs e)
        {
            PictureBox pb = sender as PictureBox;
            pb.Size = new Size(64, 64);
            pb.Location = new Point(717, 228);                                    
        }        

        private void pictureBoxJoin_MouseUp(object sender, MouseEventArgs e)
        {
            PictureBox pb = sender as PictureBox;
            pb.Size = new Size(64, 64);
            pb.Location = new Point(717, 228);
        }

        private void pictureBoxJoin_MouseDown(object sender, MouseEventArgs e)
        {
            PictureBox pb = sender as PictureBox;
            pb.Size = new Size(50, 50);
            pb.Location = new Point(724, 235);
        }

        private void dataGridViewSplit_Click(object sender, EventArgs e)
        {
            if (dataGridViewSplit.RowCount > 0)
            {
                rowIndex = dataGridViewSplit.SelectedRows[0].Index;
                System.Diagnostics.Debug.WriteLine("row enter: " + dataGridViewSplit.SelectedRows[0].Index);
                textBox1.Text = dataGridViewSplit[2, rowIndex].Value.ToString();
                textBox2.Text = dataGridViewSplit[3, rowIndex].Value.ToString();
            }
            else
            {
                textBox1.Text = "0";
                textBox2.Text = "0";
            }
        }

        #region // kerjaan mp
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            if (textBox1.Focused)
            {
                if (dataGridViewSplit.RowCount > 0)
                {
                    if (textBox1.Text == "")
                    {
                        textBox1.Text = "1";
                    }

                    int value = Int32.Parse(textBox1.Text);
                    int newSplit = Int32.Parse(dataGridViewSplit[1, rowIndex].Value.ToString());
                    newSplit /= value;
   
                    dataGridViewSplit[3, rowIndex].Value = newSplit;
                    textBox2.Text = dataGridViewSplit[3, rowIndex].Value + "";
                    dataGridViewSplit[2, rowIndex].Value = textBox1.Text;                
                }
            }
        }
        #endregion

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            if (textBox2.Focused)
            {
                if (dataGridViewSplit.RowCount > 0)
                {
                    if (textBox2.Text == "")
                    {
                        textBox2.Text = "1";
                    }

                    int value = Int32.Parse(textBox2.Text);
                    int newSplit = Int32.Parse(dataGridViewSplit[1, rowIndex].Value.ToString());
                    newSplit /= value;

                    dataGridViewSplit[2, rowIndex].Value = newSplit;
                    textBox1.Text = dataGridViewSplit[2, rowIndex].Value + "";
                    dataGridViewSplit[3, rowIndex].Value = textBox2.Text;
                }
            }
        }

        private void label5_DragDrop(object sender, DragEventArgs e)
        {
            string[] droppedFilePaths = (string[])e.Data.GetData(DataFormats.FileDrop);

            foreach (string path in droppedFilePaths)
            {
                FileInfo fi = new FileInfo(path);
                //size ditampilkan dalam KB
                joinFileList.Add(new FileRow { filepath = fi.Name, size = "" + (fi.Length / 1024), progress = "0%", splitCount = 10 });
            }
            joinSource.ResetBindings(false);

            Label label = sender as Label;
            label.Visible = false;
            label.Enabled = false;
        }

        private void label5_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        }

        private void label5_DragLeave(object sender, EventArgs e)
        {
        }

        private void label4_DragDrop(object sender, DragEventArgs e)
        {
            Label label = sender as Label;
            label.Visible = false;
            label.Enabled = false;

            string[] droppedFilePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
            int defaultSplitCount = 5;

            foreach (string path in droppedFilePaths)
            {
                FileInfo fi = new FileInfo(path);
                //size ditampilkan dalam KB                
                splitFileList.Add(new FileRow { filepath = fi.Name, size = "" + (fi.Length / 1024), splitCount = defaultSplitCount, splitSize = (fi.Length / (defaultSplitCount * 1024)), progress = "0%" });
            }
            splitSource.ResetBindings(false);
        }

        private void label4_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        }

        private void label4_DragLeave(object sender, EventArgs e)
        {
        }

        private void dataGridViewSplit_Click_1(object sender, EventArgs e)
        {
            if (dataGridViewSplit.RowCount > 0)
            {
                rowIndex = dataGridViewSplit.SelectedRows[0].Index;
                System.Diagnostics.Debug.WriteLine("row enter: " + dataGridViewSplit.SelectedRows[0].Index);
                textBox1.Text = dataGridViewSplit[2, rowIndex].Value.ToString();
                textBox2.Text = dataGridViewSplit[3, rowIndex].Value.ToString();
            }
            else
            {
                textBox1.Text = "0";
                textBox2.Text = "0";
            }
        }
    }

    #region // kerjaan mp
    #endregion // kerjaan mp

    class FileRow
    {
        public string filepath { get; set; }
        public string size { get; set; }        
        public int splitCount { get; set; }        
        public float splitSize { get; set; }
        public string progress { get; set; }
        public int realProgress { get; set; } // dalam satuan file yang berhasil digabung atau dijoin        
    }

}
